跳到主要内容

E1 SDK开发指南

一、关于E1

(一)部件名称

信息

E1 整机分为上半身和下半身,具备个23自由度。单臂拥有5个自由度,包括(右手坐标系):

  • 肩关节pitch
  • 肩关节roll
  • 上臂关节yaw
  • 手肘关节pitch
  • 下臂关节yaw

单腿拥有6个自由度,包括:

  • 胯关节yaw
  • 髋关节roll
  • 髋关节pitch
  • 膝关节pitch
  • 踝关节pitch
  • 踝关节roll

腰关节拥有一个自由度,包括:

  • 腰关节yaw

拥有多个关节电机自由度,使得E1机器人能够实现精确的运动和姿态控制。

详细信息如下

正面视图背面视图
参数E1E1 -教育版
高宽厚(站立)1400mm*485mm*320mm1400mm*485mm*320mm
带电池重量约40kg约40kg
总自由度23~2823~28
单腿自由度6 (可加选2自由度)6 (可加选2自由度)
单手臂自由度55
腰部自由度11
算力模块/Jetson Orin Nano Super
关节通讯方式Ethercat & CanfdEthercat & Canfd
关节电机通信波特率1M1M
关节最大扭矩150N.m150N.m
小腿+大腿长度约0.7M约0.7M
手臂臂展约0.6M约0.6M
关节编码器双编码器双编码器
散热系统局部风冷散热局部风冷散热
供电方式锂电池锂电池
基础算力6Tops6+67Tops
感知传感器IMU 深度相机IMU 深度相机
麦克风阵列标配标配
扬声器标配标配
高算力模组/NVIDIA Jetson Orin
智能电池(快拆)快拆电池 48v 10.5 Ah快拆电池 48v 10.5 Ah
充电器
遥控手柄
续航时间2~4H2~4H
二次开发/

(二)电气接口

在E1背面,提供电气接口如下:

类型数量
以太网1
USB2
Type-C1
HDMI1
XT30 对外供电12V(MAX 5A)1

其中HDMI接口接到的是运控板(RK3588S)上面,如果用户购买的是教育版本,目前只能通过ssh访问二开算力板(NVIDIA jetson orin nano super)

(三)机载计算机

类型型号用户密码IP算力频率内存
运控板瑞星微 RK3588S运控板不对用户开放运控板不对用户开放192.168.55.1026 Tops2.4GHz8+64GB
二开算力板NVIDIA Jetson orin nano supernoetixe1192.168.55.10167 Tops1.7GHz8+128GB

二开算力板仅教育版本的E1特有

危险

运控板(瑞星微 RK3588S)不面向用户开放,如果用户私自访问运控板,导致机器人运控程序失控,造成损失与我司无关

(四)相机信息

英特尔® 实感™ 深度摄像头 D435i - 产品规格 | 英特尔

(五)电池信息

参数信息
品牌深圳格瑞普
型号GRP6752097-13S1P
容量5100mAh
电压48V

二、使用说明

(一)使用流程及注意事项

信息

建议您在日常演示,尤其是二次开发中,全程使用保护支架悬挂E1,以更好的保护E1设备

危险

原厂运控功能暂不支持上下楼梯,请在平坦开阔处操作E1机器人,同时请远离人群,避免摔倒伤人、损坏机器哦

信息

使用流程

将机器人从包装箱中取出,推荐将机器人吊在架子上启动,或者也可以让机器人躺/趴在地上启动

安装电池

安装电池:双手同时按住电池把手上的红色按钮提起把手,将电池放入电池仓(电池指示灯在下),将电池完全放入后(卡扣卡紧)按住把手红色按钮将把手放下锁住电池。

注意事项:放电池时注意电池方向,按钮在上指示灯在下 (看下方电池示意图)

安装手柄接收器

安装手柄接收器:将手柄USB接收器 插入机器人背后任意一个USB接口,确保不虚接不松动。

启动机器

电池插入机器人背部后,先短按电池上的开机按钮,等指示灯亮起之后,长按按钮,此时会有流水灯的效果,观察机器人各部位指示灯亮起,标识开机。

配对手柄

如果手柄和接收器第一次配对时候,需要在机器人开机状态并已经插上手柄接收器后,长按手柄上面的home按键,直至指示灯常亮,此时松手,指示灯快速闪烁进入配对模式。当手柄震动后,并且下面三个指示灯常亮后代表配对成功

已经配对过之后,后续可以直接点按home按键可直接记忆配对

以下操作以澳加狮手柄举例

进入行走模式

机器人开机后,等待10秒左右会自动进入使能模式(阻尼模式)

待机器人进入使能模式后,使机器人站直于地面,按 LB & - 让机器人进入准备模式

观察机器人是否出现双腿微屈的情况,出现后 按 LB & X 进入走路模式,如果未出现双腿弯曲,重复上一步

注意:机器人不能走高于5cm的楼梯或者障碍,不能走大于20度的斜坡(有倒地风险)

后续操作请看下面按键功能图表

后续操作请看下面流程图与按键功能图表

关机流程

使用完后,此时需要扶住机器人按 LB & - 让机器人回到准备模式,此时机器失去自主站立的能力,需要人扶住。

将机器人吊起或者放平躺(趴)后,按 + 号键,让机器人进入失能模式

然后长按电机开关,关机后取下电池即可。

使用流程图:

  • 黑色往左的箭头为正常关机流程
  • 紫色往右的箭头为正常使用流程
  • 除了失能模式在其他任何模式下按下急停(+号)都会进入失能模式,使用的时候注意,避免误触

手柄按键功能表格

  1. 基本功能
前置条件键位功能备注
失能/使能模式+使能和失能机器人开机后自动进入使能模式,非关机操作不用按
使能模式LB & -屈腿准备模式此时不能自主平衡需人工保持站立
准备模式LB & X走路模式执行完手部动作后,进入走路模式可以复位
走路模式A预设握手动作重新进入走路模式复位
走路模式B预设打招呼动作重新进入走路模式复位
走路模式Y预设欢呼动作重新进入走路模式复位
走路模式LB & Y跑步模式请预留足够的空间和停止一米左右提前量
走路/跑步模式左摇杆前进和后退
走路/跑步模式右摇杆左右转向
危险

澳加狮手柄的“+”按键是控制机器人使能/失能,也可以用于在紧急状态下急停机器人 在机器人正常运行状态下,注意不要按下或误触“+”键,否则机器人会立刻失能倒地,避免造成损失

手柄按键功能图

下图按键功能 没有前后关系,不是顺序操作

  1. 示教功能
键位前置条件功能备注
RB & Y走路模式进入示教状态
RB & B示教状态结束示教
RB & X结束示教保存示教接下来按 [A, B, X, Y]保存到对应的按键上
RB & LB + \[A, B, X, Y\]走路模式播放对应按键下保存的示教动作播放完切忌要切换到走路模式

  1. 舞蹈功能
警告

使用舞蹈功能请遵循以下几点:

  • 请按照备注要求预留足够大的活动空间,路面一定平整不打滑
  • 电池电量在2格电及以上
  • 跳舞过程中不要用力牵着机器人,不要让机器人收到外部力量干扰
  • 部分舞蹈可以中途在接近站立时切走路模式打断 但不要在跳舞中弯腰动作时切到走路模式 PS: 请避免在光滑地面和高低不平地面使用,使用舞蹈时应有足够的施展空间运行动作。因操作环境和操作失误导致的机器人损坏,不在保修范围内。

若您收到机器人后需要测试舞蹈,首次测试需人保护,牵绳(仅做保护不向吊装绳施加额外的力),另外留出足够大的演示空间,以便您清楚了解大致使用空间后再进行后续演示,若第一次测试即出现问题,请及时联系客服人员

键位前置条件功能备注
LB & B走路模式播放太极动作(不稳定,暂未开放)请预留 6 * 6(米)的空间

手柄遥感漂移:

当手柄按键飘移或功能失灵时请参考官方使用手册进行重置或校准操作确保功能正常(请拔出接收器进行操作): https://mp.weixin.qq.com/s/cL3EBsndt2_ChM5iNgraSQ(正常情况下无需关注此手册)

注意事项:当感觉手柄失灵时 请先联系技术支持人员判断是机器人还是手柄的问题。

(二)关节电机信息

E1机器人关节电机状态数据由SDK接口获取,获取到的顺序固定,如下:

ID名称关节扭矩角度范围弧度范围
0arm_l1_joint左臂肩pitch关节27N.m[-163, 163][-2.84, 2.84]
1arm_l2_joint左臂肩roll关节27N.m[0, 135][0, 2.36]
2arm_l3_joint左臂大臂yaw关节27N.m[-150, 150][-2.62, 2.62]
3arm_l4_joint左臂肘pitch关节27N.m[-130, 10][-2.27, 0.17]
4arm_l5_joint左小臂yaw关节27N.m[-160, 160][-2.79, 2.79]
5leg_l1_joint左腿髋yaw关节90N.m[-40, 53][-0.70, 0.92]
6leg_l2_joint左腿髋roll关节90N.m[-40, 35][-0.70, 0.61]
7leg_l3_joint左腿大腿pitch关节150N.m[-85, 50][-1.48, 0.87]
8leg_l4_joint左腿膝关节pitch关节150N.m[0, 135][0, 2.36]
9leg_l5_joint左腿小腿pitch踝关节70N.m[-58, 24][-1.01, 0.42]
10leg_l6_joint左腿小腿roll踝环节70N.m[-90, 90][-1.57, 1.57]
11arm_r1_joint右臂肩pitch关节27N.m[-163, 163][-2.84, 2.84]
12arm_r2_joint右臂肩roll关节27N.m[-135, 0][-2.36, 0]
13arm_r3_joint右臂大臂yaw关节27N.m[-150, 150][-2.62, 2.62]
14arm_r4_joint右臂肘pitch关节27N.m[-130, 10][-2.27, 0.17]
15arm_l5_joint右小臂yaw关节27N.m[-160, 160][-2.79, 2.79]
16leg_r1_joint右腿髋yaw关节90N.m[-53, 40][40, 0.70]
17leg_r2_joint右腿髋roll关节90N.m[-35, 40][-0.61, 0.70]
18leg_r3_joint右腿大腿pitch关节150N.m[-85, 50][-1.48, 0.87]
19leg_r4_joint右腿膝关节pitch关节150N.m[0, 135][0, 2.36]
20leg_r5_joint右腿小腿pitch踝关节70N.m[-58, 24][-1.01, 0.42]
21leg_r6_joint右腿小腿roll关节70N.m[-15, 15][-0.26, 0.26]
22waist_1_joint腰部yaw关节70N.m[-90, 90][-1.57, 1.57]
23备用备用备用

(三)手柄按键数据映射

澳加狮手柄。button[]和按键映射表如下:

键位描述Button index
右肩键1
左肩键2
X5
Y6
B7
A8
+9
-10
11
左遥感按下12

手柄摇杆数据范围

最小值最大值
-11

(四)视频教程

  1. 使用教程
  1. 装箱教程

三、E1开发指南

SDK介绍

本文档介绍E1基于DDS消息中间件通信开发,本SDK采用 C/S架构,在隔离机制下,使 E1机器人的 二次开发算力板部署DDS客户端程序 与机器人上作为服务器的 运控板的运控程序500HZ 的频率下发控制命令,并持续获取当前机器人状态。dds采用的是 CYCLONEDDS 0.11.0

注意

仅配有算力板版本的E1可以使用此SDK开发

(一)系统架构图

(二)开发接口

DDS C++ Python

(三)获取SDK

https://github.com/Noetix-Robotics/noetix_sdk_e1

(四)URDF文件

请登录松延动力售后平台下载

(五)语音功能介绍

语音功能介绍:带语音交互功能的机器人头部装有环形6麦拾音器,AI声卡和扬声器,立体声音频格式为 2CH,采样率 16KHz,采样精度 16bits,并接入讯飞AI大模型(讯飞星火Spark4.0Ultra)提供问答功能。唤醒词“你好小E”,唤醒距离3M内,休眠等待时间30s,主控内置运营商专用4G-SIM卡,月流量100G,自出厂激活日起提供一年网络服务。 注意事项:语音模块使用运营商务联SIM卡,默认自激活起提供一年流量服务,后续使用需客户自行购买数据流量服务,我司提供SIM卡号和必要的技术支持,因SIM卡损毁、或违规使用造成的后果客户自负责任。对于使用期间由运营商造成的网络连接故障等问题我司免责。

语音SDK说明

语音唤醒词“你好小E”,回答我在后 即可问答 语音二次开发(此手册只限于EDU版): https://noetixrobotics.feishu.cn/wiki/M6gkwQMXji9jEFkK8uvcIYLHnfd https://noetixrobotics.feishu.cn/docx/BdJddzSwqoDhd9xixobcXj9XnAe 注意事项:自行注册的AIUI平台应用有交互次数限制

(六)应用开发 Highcontrol

提示

应用开发介绍 Highcontrol 基于原厂运动控制策略进行上层调度开发,在不改变底层控制逻辑的前提下,实现机器人自动化应用的快速构建,并支持与大模型集成,打造定制化智能行为系统。

典型应用包括:

  • 结合视觉算法与原厂运控系统,实现自主感知与自主行进
  • 集成语音交互模块,实现自然语言控制
  • 接入大模型,根据输入动态生成并调用原厂控制动作(具备一定风险,需要严格安全策略)
  • 配合外挂感知雷达,实现定位导航巡检系统

简而言之,HighControl 通过对原厂控制能力的高层调度封装,实现对遥控器或 APP 可控行为的自动化与程序化调用,并在此基础上拓展部分自主化与智能化能力。

1. Highcontrol架构图

(1) 状态上报机制

当客户端 SDK 与机器人运控程序建立连接后,运控程序会持续向客户端推送机器人实时状态信息,包括:

  • 全身电机参数数据(pos 位置vel 速度tau 扭矩kpkdtemperature 温度error 错误信息
  • IMU 状态数据
  • 当前工作模式(workmode,表示当前运行的控制策略)
  • 澳加狮手柄数据(用于同步人工输入或辅助控制)
  • 电池电量及相关系统状态信息

(2) 客户端控制指令下发

客户端结合自身应用场景向运控程序发送控制指令,主要包括:

  • (x, y, z) 行进控制数据 仅在特定模式下有效,例如走路模式、握手、打招呼、欢呼、示教模式等。
  • action 指令workmode 对应,用于切换或触发机器人当前运行的算法策略。
  • data 附加 DDS 数据 通常在 PLAYTEACH(播放示教模式)下使用,用于指定示教文件索引等附加参数。

(3) 运控程序内部处理流程

运控程序接收到客户端指令后:

  • 将控制参数传递给内部控制算法
  • 算法基于强化学习模型进行策略计算
  • 生成电机目标期望值(目标位置、速度或力矩)并发送到电机控制接口
  • 将计算结果下发至硬件控制层

(4) 硬件执行层

硬件层接收目标控制数据后:

  • 执行电机控制指令
  • 完成对应的期望动作

在整个流程中,用户仅需下发部分高层控制参数。 具体的运动规划、动态平衡与电机级控制计算均由原厂运控程序中的黑盒算法完成。 因此,在 Highcontrol 模式下,用户能够调用和自动化的能力范围,原则上不超过 APP 或手柄原本可实现的功能边界,但不开放底层电机级控制权限。

2. Highcontrol运行流程图

(1) 初始化阶段(init)

系统启动后完成以下初始化流程:

  1. 建立客户端与机器人运控程序之间的通信连接
  2. 注册机器人状态数据接收回调函数

(2) 状态数据回调机制

运控程序持续向客户端推送机器人状态数据。

回调函数接收到数据后进行封装,并分别存入缓冲区及全局状态变量:

  • motor_state_buffer_:电机状态缓冲区
  • imu_buffer_:IMU 状态缓冲区
  • joy_buffer_:手柄数据缓冲区
  • curmode:当前运控策略模式(全局变量)

该阶段仅负责数据接收与缓存,不进行控制决策计算。


3. HighController参数表及常用接口使用

接口名称接口描述返回类型
instance获取HighController单例指针对象指针
initHighController对象初始化
publish_cmd发布DDS控制命令数据
get_mode获取当前机器人策略模式int
from_dds_get_joydata从DDS订阅中获取手柄数据手柄数据结构体
get_imu_data从DDS订阅中获取imu数据IMU数据结构体
get_joint_state从DDS订阅中获取电机数据电机数据结构体数组

获取HighController对象单例

函数名instance
函数原型static HighController *Instance()
功能概述获取 HighController单例
参数
返回值HighController单例对象指针
备注

C++示例:

HighController *ctrl = HighController::Instance();

Python示例:

ctrl = HighController.instance()

HighController对象初始化

函数名init
函数原型bool init()
功能概述HighController对象初始化
参数
返回值bool
备注

C++示例:

ctrl->init()

Python示例:

ctrl.init()

发布机器人控制指令

函数名publish_cmd
函数原型void publish_cmd(double ver, double hor, double yaw, ControlCmd action, uint16_t index)
功能概述使用HighController发送dds控制指令
参数• ver 范围:[-1, 1];机器人纵向移动值(>0 前进)
• hor 范围:[-1, 1];机器人转向值(>0 左转)
• action 机器人模式切换枚举
• index 示教相关模式指定索引
返回值
备注此接口不能连续调用,否则机器人接收指令太快会无法响应,需要在每次指令发送至少添加2ms的延时

C++示例:

ctrl->publish_cmd(0, 0, ControlCmd.CHEER, 0);

Python示例:

ctrl.publish_cmd(0, 0, ControlCmd.CHEER, 0)

action参数表示切换机器人到对应模式

参数名称定义原型序号示例值说明
ControlCmd
enum class ControlCmd :
uint8_t {
WALK,
SWING,
SHAKE,
CHEER,
RUN,
START,
SWITCH,
STARTTEACH,
SAVETEACH,
ENDTEACH,
PLAYTEACH,
TAIJI,
DEFAULT
};
0WALK走路模式(LB & X)
1SWING出厂预设动作挥手(B)
2SHAKE出厂预设动作握手(A)
3CHEER出厂预设动作欢呼(Y)
4RUN跑步模式(LB & Y)
5START使能/失能(及停)
6SWITCH准备模式(LB & —)
7STARTTEACH开始示教(RB & Y)
8SAVETEACH保存示保存示教(RB & B and RB & X) ps: 目前下发SAVETEACH,会先发送ENDTEACH在发送SAVETEACH,相等于将两个步骤简化为了一个 保存文件根据参数file_index,具体可以参考HighController::set_axes接口
9ENDTEACH结束示教(RB & B)
10PLAYTEACH播放示教(RB & LB &file_index) 根据file_index播放对应文件示教动作
11DEFAULT空指令

DEFAULT空模式使用目的

整个机器人线程会循环执行process控制函数是周期循环执行的,如果在其中持续下发action = ControlCmd::CHEER; 等动作或者切换模式的命令的话,机器人会在欢呼动作尚未完成时不断收到新的CHEER指令,导致动作被反复打断,表现为机器人“卡住、无反应”。

正确做法

CHEER 属于一次性触发指令(事件),应只发送一次;后续循环发送 DEFAULT(空指令),避免重复触发。

示例代码(修正后)

if (is_first) {
action = ControlCmd::CHEER; // 只触发一次
is_first = false;
} else {
action = ControlCmd::DEFAULT;
}

效果

  • 收到 CHEER → 触发并完整执行欢呼动作
  • 后续 DEFAULT → 不再打断动作
  • 机器人行为正常、可预期 动作类指令要“边沿触发”,不能在控制循环里持续下发。

index用于在示教相关模式下指定示教文件索引

ctrl.publish_cmd(0, 0, ControlCmd.STARTTEACH, 0) # 开始示教
sleep(10) # 录制示教动作
ctrl.publish_cmd(0, 0, ControlCmd.SAVETEACH, 1) # 结束并保存示教动作,指定索引为1
sleep(2) # 让运控程序执行完保存流程,防止被下条命令打断
ctrl.publish_cmd(0, 0, ControlCmd.PLAYTEACH, 1) # 播放示教文件1
信息

仅当 action 为以下模式时: PLAYTEACH / WALK / SWING / CHEER / SHAKE / DEFAULT 参数 xyaw 才会生效,用于控制机器人运动;在其他模式下,xyaw 无效。

获取当前机器人策略模式

函数名get_mode
函数原型int get_mode()
功能概述获取DDS机器人当前策略模式
参数
返回值int
备注

C++示例:

int curmode = ctrl->get_mode();

Python示例:

curmode = ctrl.get_mode()

get_mode 返回数据对应表

workmode值说明
0使能模式
1准备模式
2走路模式
3跑步模式
7出厂预设动作打招呼
8出厂预设动作握手
9出厂预设动作欢呼
10开始示教
11结束示教
27播放示教
13保存示教1
28太极动作
26保存示教2
29失能模式
信息

保存示教 SDK向机器人发送 SAVETEACH 后,机器人会陆续返回 退出示教 保存示教1 保存示教2 三个状态

危险

保护模式 在处于站立控制策略(走路,示教,舞蹈等下,运控程序会对 IMU 姿态数据进行持续监测。 当检测到姿态偏离站立稳定区间,并超过预设阈值时,系统将立即触发保护机制,强制切换至安全模式。 在保护模式下:

  • 全身关节进入失能状态(电机停止主动输出)
  • 终止当前运动控制策略
  • 阻断进一步动作指令执行 该机制的目的在于:
  • 防止机器人在跌倒或失稳过程中持续输出控制力矩
  • 避免四肢失控摆动造成二次损伤
  • 降低对设备本体及周围环境的潜在损害 该保护逻辑属于底层安全防护机制,具有最高优先级,不受上层控制指令影响。

获取DDS订阅的手柄数据

函数名from_dds_get_joydata
函数原型const joydata from_dds_get_joydata()
功能概述获取DDS手柄输入数据
参数
返回值joydata结构体
备注
参数名称定义原型示例值说明
joydata
struct joydata {
double axes[2];
int button[14];
};
axes遥控器遥感线性数值
button遥控器按键按下映射
数值 1 被按下,0 正常
手柄摇杆映射映射说明范围
axes[0]右摇杆左右推动值[-1, 1]
axes[1]左摇杆前后推动值[-1, 1]

C++示例:

joydata jsdata = ctrl->from_dds_get_joydata();
for (int i = 0; i < 14; i++)
std::cout << jsdata.button[i] << std::endl;
std::cout << jsdata.axes[0] << std::endl;
std::cout << jsdata.axes[1] << std::endl;

Python示例:

jsdata = ctrl.from_dds_get_joydata()
for i in range(14):
print(jsdata.button[i])
print(jsdata.axes[0])
print(jsdata.axes[1])

获取DDS订阅IMU数据

函数名get_imu_data
函数原型const NingImuData get_imu_data()
功能概述获取imu数据
参数
返回值NingImuData结构体
备注
参数名称定义原型示例值说明
NingImuData
struct NingImuData {
double ori[4];
double ori_cov[9];
double angular_vel[3];
double angular_vel_cov[9];
double linear_acc[3];
double linear_acc_cov[9];
};
ori姿态四元数
ori_cov姿态协方差
angular_vel角速度
angular_vel_cov角速度协方差
linear_acc线加速度
linear_acc_cov线加速度协方差

C++示例:

NingImuData imu_data = ctrl->get_imu_data();

for (int i = 0; i < 4; i++)
std::cout << imu_data.ori[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.ori_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.angular_vel[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.angular_vel_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.linear_acc[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.linear_acc_cov[i] << std::endl;

Python示例:

imu_data = ctrl.get_imu_data()

for i in range(4):
print(imu_data.ori[i])
for i in range(9):
print(imu_data.ori_cov[i])
for i in range(3):
print(imu_data.angular_vel[i])
for i in range(9):
print(imu_data.angular_vel_cov[i])
for i in range(3):
print(imu_data.linear_acc[i])
for i in range(9):
print(imu_data.linear_acc_cov[i])

获取DDS订阅的电机信息数据

函数名get_joint_state
函数原型const std::array<MotorState, 24> get_joint_state()
功能概述获取机器人电机状态数据
参数
返回值MotorState结构体数组
备注
参数名称定义原型示例值说明
MotorState
struct MotorState {
double pos;
double vel;
double tau;
uint16_t motor_id;
uint8_t error;
int temperature;
};
pos电机位置
vel电机转速
tau电机扭矩
motor_id电机ID
error

电机错误码:

  • 02H:电机过流
  • 03H:电机电压过低
  • 04H:电机编码器错误
  • 06H:电机制动电压过高
  • 07H:DRV驱动错误
  • 08H:超压
  • 09H:欠压
  • 0AH:过流
  • 0BH:MOS过温
  • 0CH:电机线圈过温
  • 0DH:通讯丢失
  • 0EH:过载
temperature温度

C++示例:

std::array<MotorState, 24> joint_state = ctrl->get_joint_state();

for (int i = 0; i < 24; i++) {
std::cout << joint_state[i].pos << std::endl;
std::cout << joint_state[i].vel << std::endl;
std::cout << joint_state[i].tau << std::endl;
std::cout << joint_state[i].motor_id << std::endl;
std::cout << static_cast<int>(joint_state[i].error) << std::endl;
std::cout << joint_state[i].temperature << std::endl;
}

Python示例:

joint_state = ctrl.get_joint_state()

for i in range(24):
print(joint_state[i].pos)
print(joint_state[i].vel)
print(joint_state[i].tau)
print(joint_state[i].motor_id)
print(joint_state[i].error)
print(joint_state[i].temperature)

4.运控状态切换流程图

危险

注意:使用highcontrol开发过程中,模式切换请遵循上述流程图以确保合理安全

5.Demo例程介绍

SDK 文件夹中的 example_high.cpptest_high.py 提供了一个示例 Demo,用于解析澳加狮手柄输入数据,并根据手柄操作生成对应控制指令发送至机器人。

(七)运控开发 Lowcontrol

运控开发介绍 Lowcontrol 将运控程序中的电机控制接口开放至 SDK,允许用户以 500Hz 的控制频率直接调节底层电机参数。结合强化学习算法部署,可实现对 Bumi 运动能力的深度定制,使其完成多样化的新动作与舞蹈等复杂行为。

1. E1训练框架

https://github.com/Noetix-Robotics/noetix_e1_lab.git

2. Lowcontrol架构图

(1) 状态数据上报

当客户端 SDK 与机器人运控程序建立连接后,运控程序会持续向客户端推送机器人实时状态信息,包括:

  • 全身电机参数数据(pos位置、vel速度、tau扭矩、kp、kd、temperature 温度、error 错误信息
  • IMU 状态数据
  • 澳加狮手柄数据(用于同步人工输入或辅助控制)
(2) 客户端侧控制计算

客户端结合自身算法(通常为强化学习模型)进行实时策略计算,生成各电机的目标期望值(如目标位置等),并将电机控制指令数组写入缓冲区后下发至运控程序。

(3) 运控程序转发机制

运控程序接收到客户端下发的电机指令数组后,不进行高层策略计算,而是直接将控制参数转发至硬件控制层。

(4) 硬件执行层

硬件层接收电机目标参数后执行控制指令,驱动电机完成期望动作。

在 LowControl 模式下:

  • 强化学习模型部署在客户端侧
  • 用户可直接参与电机级控制
  • 运控程序主要承担通信与安全转发职责
  • 控制频率可达 500Hz 该模式具备更高的控制自由度与灵活性,但同时也意味着:
  • 对算法稳定性要求更高
  • 对实时性与系统安全性的要求更严格
  • 若控制策略不稳定,可能直接影响机器人运动安全

3. Lowcontrol运行流程图

(1)初始化阶段(init)

系统启动后完成以下初始化步骤: a. 建立客户端与机器人运控程序之间的通信连接 b. 注册机器人状态数据接收回调函数 c. 创建 send_thread :数据发送线程

(2)状态数据回调机制

运控程序持续向客户端推送机器人状态数据。 回调函数接收数据后进行封装,并存入对应缓冲区或全局变量:

  • motor_state_buffer_:电机状态缓冲区
  • imu_buffer_:IMU 状态缓冲区
  • joy_buffer_:手柄数据缓冲区 该阶段仅负责数据接收与缓存,不参与控制策略计算。
(3)send_thread(数据发送线程)

数据发送线程同样以 2ms 周期运行:

  • motor_cmd_buffer_ 不为空
  • 读取最新电机控制指令
  • 将电机目标数组发送至运控程序 运控程序仅负责数据转发至硬件层,不参与高层控制决策。
(4)架构特征

Lowcontrol 模式的核心特征是:

  • 客户端直接参与电机级控制
  • 强化学习或自定义控制算法运行在客户端
  • 运控程序不再负责高层策略计算,仅承担通信与安全转发职责
  • 控制频率可达 500Hz 该模式提供更高的控制自由度与算法可塑性,但同时对:
  • 实时性
  • 算法稳定性
  • 线程安全与调度精度 提出更高要求。
4. 关节电机信息
ID名称关节扭矩角度范围弧度范围
0arm_l1_joint左臂肩pitch关节27N.m[-163, 163][-2.84, 2.84]
1arm_l2_joint左臂肩roll关节27N.m[0, 135][0, 2.36]
2arm_l3_joint左臂大臂yaw关节27N.m[-150, 150][-2.62, 2.62]
3arm_l4_joint左臂肘pitch关节27N.m[-130, 10][-2.27, 0.17]
4arm_l5_joint左小臂yaw关节27N.m[-160, 160][-2.79, 2.79]
5leg_l1_joint左腿髋yaw关节90N.m[-40, 53][-0.70, 0.92]
6leg_l2_joint左腿髋roll关节90N.m[-40, 35][-0.70, 0.61]
7leg_l3_joint左腿大腿pitch关节150N.m[-85, 50][-1.48, 0.87]
8leg_l4_joint左腿膝关节pitch关节150N.m[0, 135][0, 2.36]
9leg_l5_joint左腿小腿pitch踝关节70N.m[-58, 24][-1.01, 0.42]
10leg_l6_joint左腿小腿roll踝环节70N.m[-90, 90][-1.57, 1.57]
11arm_r1_joint右臂肩pitch关节27N.m[-163, 163][-2.84, 2.84]
12arm_r2_joint右臂肩roll关节27N.m[-135, 0][-2.36, 0]
13arm_r3_joint右臂大臂yaw关节27N.m[-150, 150][-2.62, 2.62]
14arm_r4_joint右臂肘pitch关节27N.m[-130, 10][-2.27, 0.17]
15arm_l5_joint右小臂yaw关节27N.m[-160, 160][-2.79, 2.79]
16leg_r1_joint右腿髋yaw关节90N.m[-53, 40][40, 0.70]
17leg_r2_joint右腿髋roll关节90N.m[-35, 40][-0.61, 0.70]
18leg_r3_joint右腿大腿pitch关节150N.m[-85, 50][-1.48, 0.87]
19leg_r4_joint右腿膝关节pitch关节150N.m[0, 135][0, 2.36]
20leg_r5_joint右腿小腿pitch踝关节70N.m[-58, 24][-1.01, 0.42]
21leg_r6_joint右腿小腿roll关节70N.m[-15, 15][-0.26, 0.26]
22waist_1_joint腰部yaw关节70N.m[-90, 90][-1.57, 1.57]
23备用备用备用
5. 澳加狮手柄数据映射

澳加狮手柄。button[]和按键映射表如下:

键位描述Button index
右肩键1
左肩键2
X5
Y6
B7
A8
+9
-10
11
左遥感按下12
手柄摇杆映射映射说明范围
axes[0]右摇杆左右推动值[-1, 1]
axes[1]左摇杆前后推动值[-1, 1]

手柄摇杆数据范围

最小值最大值
-11
6. LowController常用接口及使用例程
接口名称接口描述返回类型
instance获取LowController单例指针对象指针
initLowController对象初始化
set_joint将电机控制命令写入缓冲区
get_mode获取当前机器人策略模式int
from_dds_get_joydata从DDS订阅中获取手柄数据手柄数据结构体
get_imu_data从DDS订阅中获取imu数据IMU数据结构体
get_joint_state从DDS订阅中获取电机数据电机数据结构体数组

获取LowController对象单例

函数名instance
函数原型static LowController *Instance()
功能概述获取 HighController单例
参数
返回值LowController单例对象指针
备注

C++示例:

LowController *ctrl = LowController::Instance();

Python示例:

ctrl = LowController.instance()

LowController对象初始化

函数名init
函数原型bool init()
功能概述LowController对象初始化
参数
返回值bool
备注

C++示例:

ctrl->init()

Python示例:

ctrl.init()

电机控制命令数组存入缓冲区 存入缓冲区后,会由 send_thread 线程自动发送

函数名set_joint
函数原型void set_joint(std::array<MotorCmd, 24> motorcmd)
功能概述设置关节数据
参数- motorcmd 电机命令结构体
返回值
备注
参数名称定义原型示例值说明
MotorCmd
struct MotorCmd {
double pos;
double vel;
double tau;
double kp;
double kd;
uint16_t motor_id;
};
pos电机位置
vel电机转速
tau电机扭矩
kpPID参数
kdPID参数
motor_id电机ID
危险

电机控制命令下发请严格参考 关节电机信息 中的指定参数范围

C++示例:

std::array<MotorCmd, 24> motorcmd;
// 省略算法逻辑 ...
ctrl->set_joint(motorcmd);

Python示例:

cmds = [MotorCmd() for _ in range(24)]
# 省略算法逻辑 ...
ctrl.set_joint(cmds)

根据关节电机名称获取对应关节电机ID

函数名getJointsIndex
函数原型int getJointsIndex(std::string jointname)
功能概述根据关节电机名称获取对应关节电机ID
参数jointname:关节电机名称
返回值int:对应关节电机ID
备注

C++示例:

int id = ctrl->getJointsIndex("arm_l1_joint");

Python示例:

id = ctrl.getJointsIndex("arm_l1_joint");
函数名from_dds_get_joydata
函数原型const joydata from_dds_get_joydata()
功能概述获取DDS手柄输入数据
参数
返回值joydata结构体
备注
参数名称定义原型示例值说明
joydata
struct joydata {
double axes[2];
int button[14];
};
axes遥控器遥杆线性数值
button

遥控器按键按下映射


数值 1 被按下,0 正常

手柄摇杆映射映射说明范围
axes[0]右摇杆左右推动值[-1, 1]
axes[1]左摇杆前后推动值[-1, 1]

C++示例:

joydata jsdata = ctrl->from_dds_get_joydata();
for (int i = 0; i < 14; i++)
std::cout << jsdata.button[i] << std::endl;
std::cout << jsdata.axes[0] << std::endl;
std::cout << jsdata.axes[1] << std::endl;

Python示例:

jsdata = ctrl.from_dds_get_joydata()
for i in range(14):
print(jsdata.button[i])
print(jsdata.axes[0])
print(jsdata.axes[1])
函数名get_imu_data
函数原型const NingImuData get_imu_data()
功能概述获取imu数据
参数
返回值NingImuData结构体
备注
参数名称定义原型示例值说明
NingImuData
struct NingImuData {
double ori[4];
double ori_cov[9];
double angular_vel[3];
double angular_vel_cov[9];
double linear_acc[3];
double linear_acc_cov[9];
};
ori姿态四元数
ori_cov姿态协方差
angular_vel角速度
angular_vel_cov角速度协方差
linear_acc线加速度
linear_acc_cov线加速度协方差

C++示例:

NingImuData imu_data = ctrl->get_imu_data();

for (int i = 0; i < 4; i++)
std::cout << imu_data.ori[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.ori_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.angular_vel[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.angular_vel_cov[i] << std::endl;
for (int i = 0; i < 3; i++)
std::cout << imu_data.linear_acc[i] << std::endl;
for (int i = 0; i < 9; i++)
std::cout << imu_data.linear_acc_cov[i] << std::endl;

Python示例:

imu_data = ctrl.get_imu_data()

for i in range(4):
print(imu_data.ori[i])
for i in range(9):
print(imu_data.ori_cov[i])
for i in range(3):
print(imu_data.angular_vel[i])
for i in range(9):
print(imu_data.angular_vel_cov[i])
for i in range(3):
print(imu_data.linear_acc[i])
for i in range(9):
print(imu_data.linear_acc_cov[i])
函数名get_joint_state
函数原型const std::array<MotorState, 24> get_joint_state()
功能概述获取机器人电机状态数据
参数
返回值MotorState结构体数组
备注
参数名称定义原型示例值说明
MotorState
struct MotorState {
double pos;
double vel;
double tau;
uint16_t motor_id;
uint8_t error;
int temperature;
};
pos电机位置
vel电机转速
tau电机扭矩
motor_id电机ID
error

电机错误码:

  • 02H:电机过流
  • 03H:电机电压过低
  • 04H:电机编码器错误
  • 06H:电机制动电压过高
  • 07H:DRV驱动错误
  • 08H:超压
  • 09H:欠压
  • 0AH:过流
  • 0BH:MOS过温
  • 0CH:电机线圈过温
  • 0DH:通讯丢失
  • 0EH:过载
temperature温度

C++示例:

std::array<MotorState, 24> joint_state = ctrl->get_joint_state();

for (int i = 0; i < 24; i++) {
std::cout << joint_state[i].pos << std::endl;
std::cout << joint_state[i].vel << std::endl;
std::cout << joint_state[i].tau << std::endl;
std::cout << joint_state[i].motor_id << std::endl;
std::cout << static_cast<int>(joint_state[i].error) << std::endl;
std::cout << joint_state[i].temperature << std::endl;
}

Python示例:

joint_state = ctrl.get_joint_state()

for i in range(24):
print(joint_state[i].pos)
print(joint_state[i].vel)
print(joint_state[i].tau)
print(joint_state[i].motor_id)
print(joint_state[i].error)
print(joint_state[i].temperature)

获取澳加狮手柄数据(带算力板的Bumi 算力板直接获取) AoLionDriver类

AoLionDriver类接口
接口名称接口描述
init初始化
getremotedata获取手柄数据
函数名init
函数原型bool init(std::string port, int baudrate)
功能概述初始化手柄设备端口
参数
  • port:设备端口号,默认为 /dev/input/js0
  • baudrate:波特率,默认为 115200
返回值
  • true:初始化成功
  • false:初始化失败
备注
函数名getremotedata
函数原型const joydata getremotedata()
功能概述获取手柄数据
参数
返回值joydata:手柄数据结构体
备注
使用示例

C++示例:

AoLionDriver aoliondriver;
joydata remote_data;
aoliondriver.init("/dev/input/js0", 115200);
const joydata jdata=aoliondriver.getremotedata();
for (int i = 0; i < 14; i++)
std::cout << jdata.button[i] << std::endl;
std::cout << jdata.axes[0] << std::endl;
std::cout << jdata.axes[1] << std::endl;

Python示例:

al = AoLionDriver()
al.init("/dev/input/js0", 115200)
jdata = al.getremotedata()
for i in range(14):
print(jdata.button[i])
print(jdata.axes[0])
print(jdata.axes[1])
7. Demo例程介绍

examples_cpp/example_low.cpp和 中运行了一个E1的24个自由度的走路策略(policy/policy.onnx)的sim2real(算法模型实机部署)的代码,根据策略提供了部分强化学习部署接口

函数名loadModel
函数原型bool loadModel(std::string modelpath)
功能概述加载自有模型
参数- modelpath: 模型路径(程序所在的当前绝对路径)
返回值true:加载成功;false:加载失败
备注
函数名onnxdatainit
函数原型void onnxdatainit()
功能概述初始化onnx数据
参数
返回值
备注
函数名getmodelparam
函数原型bool getmodelparam()
功能概述从yaml文件中获取模型参数
参数
返回值true:读取yaml文件成功;false:读取yaml文件失败
备注
函数名setparameter
函数原型void setparameter(Command &cmd,bool* isfirst)
功能概述设置xyz整机控制参数
参数• cmd:设置指令
• isfirst:是否是第一次设置
返回值
备注
函数名updatestateestimation
函数原型bool updatestateestimation()
功能概述更新状态,包括关节角度,IMU数据等从yaml文件中获取模型参数
参数
返回值true:读取yaml文件成功;false:读取yaml文件失败
备注
函数名computeObservation
函数原型void computeObservation()
功能概述计算观测系数
参数
返回值
备注
函数名computeActions
函数原型void computeActions()
功能概述计算最终的动作
参数
返回值
备注

手柄操作流程

按键组合功能说明
+全身关节回0位进入阻尼模式
LB & -四肢微微弯曲,进入策略前准备模式
LB & X进入策略控制走路模式

(八)快速开发

以下所有操作都是在E1算力板上进行,算力板本身已经安装好所需编译环境,也可以通过docker部署编译环境

外挂开发部署环境请看:https://noetixrobotics.feishu.cn/docx/PP2BdXkSUoQ2VOxctJKcEdHanAg

信息

外挂开发介绍

由于人形产品的运控板不对外开放,用户程序无法直接部署在运控板上运行,因此需要额外的计算载体来执行用户程序。 如果用户购买的机型未配备算力板,则需采用“外挂开发”方式:用户自备算力板或主机,通过网线连接 E1后背接口,与运控板通信。 由于运控板仅允许与原版算力板的固定 IP 通信,且通信基于内部交换机的有线连接,因此外挂设备需配置为与原版算力板相同的 IP,以模拟原始算力板完成接入。

有线连接算力板 SSH登录

ssh noetix@192.168.55.101
1. SDK目录结构
.
├── build.sh # 编译脚本
├── CMakeLists.txt
├── config # 模型配置文件 DDS配置文件等
├── examples_cpp # C++ 示例代码
├── examples_py # python 示例代码
├── include # 头文件目录
├── lib # 库文件目录
├── LICENSE
├── policy # 模型策略文件目录
├── README.md
└── src # 源文件目录
2. docker开发环境镜像部署

noetix_dds.tar.gz

危险

注意:此镜像包为aarch64架构,仅在aarch64架构电脑上可部署

1.解压压缩包

tar -zxvf noetix_dds.tar.gz

解压出来后,压缩包内会有noetix_dds.tar 开发镜像文件 noetix_dds.yaml 配置部署文件

version: "3.8"

services:
noetix_dds:
image: noetix_dds:arm64
container_name: noetix_dds
network_mode: host
volumes:
- /home/noetix/work:/home/noetix/work:rw # 挂载工作目录
# /home/noetix/work 冒号前这部分要改成用户的工作目录,创建一个/home/noetix/work/路径目录
stdin_open: true
tty: true

2.部署

docker load -i noetix_dds.tar
docker images # 确认noetix_dds arm64 镜像是否存在
mkdir -p /home/noetix/work # 创建工作目录, 用户自行选择
docker compose -f noetix_dds.yaml up -d # 部署
docker ps # 检查 noetix_dds 是否存在

3.进入容器

docker exec -it noetix_dds /bin/bash

后续将DDS SDK 放入工作目录即可开始开发

3.编译SDK
cd noetix_sdk_E1
./build.sh # 一键编译脚本

编译成功后会在SDK根目录下生成可执行文件 example_lowexample_high ,并且在build目录下生成highcontrol_py 以及 lowcontrol_py pybind库,供python调用

4.启动程序

C++

cd noetix_sdk_E1
sudo ./build/example_high # or sudo ./build/example_low

Python

cd noetix_sdk_E1
python3 examples_py/test_low.py # python3 examples_py/test_high.py
危险

安全提示:调试过程中,请全程使用机器人吊架,以免错误程序失控造成损失

(九)常见问题及注意事项

1. DDS客户端demo:运行报错(1) ARM架构:

error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory

libssl1.1_1.1.1f-1ubuntu2.16_arm64.deb

sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2.16_arm64.deb

X86架构:

error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory

libssl1.1_1.1.1f-1ubuntu2_amd64.deb

sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb